﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using EngineOfEvermore.Imaging;
using Blue.ResourceManager;
using EngineOfEvermore.Scene;
using EngineOfEvermore.Editor.Common;
using System.Diagnostics;
using EngineOfEvermore.Scene.Visual;
using EngineOfEvermore.Common;

namespace EngineOfEvermore.Editor.AnimationEditor.View
{
    partial class ImageMapView : WeifenLuo.WinFormsUI.Docking.DockContent, IImageMapView
    {
        const String SPRITE_NAME = "FRAMESPRITE";

        IInputListener _inputListener;
        List<ImageMap> _imageMaps = new List<ImageMap>();
        ImageMap _currentImageMap;
        readonly SceneGraph _sceneGraph;
        readonly MinimalSceneGraphContext _sceneGraphContext;

        public ImageMapView()
        {
            InitializeComponent();

            Debug.Assert( this.DesignMode );
        }

        public ImageMapView( IInputListener inputListener,
            GorgonRenderTargetManager renderTargetManager )
        {
            Debug.Assert( !this.DesignMode );

            InitializeComponent();

            _inputListener = inputListener;

            _sceneGraphContext = new MinimalSceneGraphContext();
            _sceneGraphContext.UpdaterTargetFps = 30;
            
            _sceneGraph = new SceneGraph();
            _sceneGraph.OnInit( _sceneGraphContext.ServiceProvider );

            _sceneView.Initialize( renderTargetManager );
            _sceneView.SceneGraph = _sceneGraph;
            _sceneView.Camera.ScaleChanged += Camera_ScaleChanged;

            GorgonLibrary.Gorgon.Idle += _updateScene;
        }

        void Camera_ScaleChanged( Camera camera, float oldScale, float newScale )
        {
            new WrappedLineSpriteArranger( new Vector2d( 4, 4 ) ).ArrangeSprites(
                        SPRITE_NAME,
                        _sceneGraph.SceneObjects,
                        _sceneView.Camera.GetDisplayedArea()
                        );
        }

        void _updateScene( object sender, GorgonLibrary.Graphics.FrameEventArgs e )
        {
            _sceneGraphContext.UpdateTimeContext();
        }

        void ImageMapView_Load( object sender, EventArgs e )
        {
            new ToolTip().SetToolTip( _loadImageMapButton, "Load an ImageMap" );
        }

        void _addImageMapButton_Click( object sender, EventArgs e )
        {
            _inputListener.OnLoadImageMapClicked();
        }

        public bool ContentEnabled
        {
            get
            {
                return _loadImageMapButton.Enabled;
            }
            set
            {
                _loadImageMapButton.Enabled = value;
                _imageMapComboBox.Enabled = value;
            }
        }

        public void LoadImageMap( string resourceName )
        {
            resourceName = ResourceManager.NormalizeName( resourceName );

            if ( !_imageMaps.Any( im => im.ResourceName == resourceName ) )
            {
                ImageMap imageMap = ResourceManager.GetResource<ImageMap>( resourceName );
                _imageMaps.Add( imageMap );

                _imageMapComboBox.Items.Add( resourceName );
            }

            this.CurrentImageMap = resourceName;
        }

        public String CurrentImageMap 
        { 
            get
            {
                return _currentImageMap != null ? _currentImageMap.ResourceName : String.Empty;
            }
            set
            {
                String resourceName = ResourceManager.NormalizeName( value );
                _currentImageMap = _imageMaps.Find( im => im.ResourceName == resourceName );

                _imageMapComboBox.SelectedItem = _currentImageMap.ResourceName;

                _sceneGraph.Clear();

                if ( _currentImageMap != null )
                {
                    List<SceneObject> sceneObjectList = new List<SceneObject>();
                    

                    for ( int i = 0; i < _currentImageMap.FrameCount; ++i )
                    {
                        SceneObject sceneObject = new SceneObject();
                        VisualComponent visualComponent = new VisualComponent();
                        StaticSprite sprite = new StaticSprite();
                        sprite.Name = SPRITE_NAME;

                        sprite.ImageMap = _currentImageMap;
                        sprite.Frame = i;

                        visualComponent.Children.Add( sprite );
                        sceneObject.AddComponent( visualComponent );

                        _sceneGraph.AddSceneObject( sceneObject );
                        sceneObjectList.Add( sceneObject );
                    }

                    new WrappedLineSpriteArranger( new Vector2d( 4, 4 ) ).ArrangeSprites( 
                        SPRITE_NAME, sceneObjectList, _sceneView.Camera.GetDisplayedArea() );
                }
            }
        }

        public void ResetView()
        {
            _imageMaps.Clear();
            _currentImageMap = null;

            _imageMapComboBox.Items.Clear();
            _imageMapComboBox.Text = "";
        }

        void _sceneView_SizeChanged( object sender, EventArgs e )
        {
            new WrappedLineSpriteArranger( new Vector2d( 4, 4 ) ).ArrangeSprites(
                        SPRITE_NAME, 
                        _sceneGraph.SceneObjects, 
                        _sceneView.Camera.GetDisplayedArea() 
                        );
        }

        void _resetZoomButton_Click( object sender, EventArgs e )
        {
            _sceneView.Camera.Scale = 1;
        }
    }
}
